home *** CD-ROM | disk | FTP | other *** search
/ Aminet 49 / Aminet 49 (2002)(GTI - Schatztruhe)[!][Jun 2002].iso / Aminet / util / libs / ttrender.lha / ttrender-2.0 / Developer / source / base / ftsynth.c < prev    next >
Encoding:
C/C++ Source or Header  |  2002-04-06  |  10.4 KB  |  400 lines

  1. /***************************************************************************/
  2. /*                                                                         */
  3. /*  ftsynth.c                                                              */
  4. /*                                                                         */
  5. /*    FreeType synthesizing code for emboldening and slanting (body).      */
  6. /*                                                                         */
  7. /*  Copyright 2000-2001 by                                                 */
  8. /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
  9. /*                                                                         */
  10. /*  This file is part of the FreeType project, and may only be used,       */
  11. /*  modified, and distributed under the terms of the FreeType project      */
  12. /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
  13. /*  this file you indicate that you have read the license and              */
  14. /*  understand and accept it fully.                                        */
  15. /*                                                                         */
  16. /***************************************************************************/
  17.  
  18.  
  19. #include <ft2build.h>
  20. #include FT_INTERNAL_OBJECTS_H
  21. #include FT_INTERNAL_CALC_H
  22. #include FT_OUTLINE_H
  23. #include FT_SYNTHESIS_H
  24.  
  25.  
  26. #define FT_BOLD_THRESHOLD  0x0100
  27.  
  28.  
  29.   /*************************************************************************/
  30.   /*************************************************************************/
  31.   /****                                                                 ****/
  32.   /****   EXPERIMENTAL OBLIQUING SUPPORT                                ****/
  33.   /****                                                                 ****/
  34.   /*************************************************************************/
  35.   /*************************************************************************/
  36.  
  37.   FT_EXPORT_DEF( FT_Error )
  38.   FT_Outline_Oblique( FT_GlyphSlot  original,
  39.                       FT_Outline*   outline,
  40.                       FT_Pos*       advance )
  41.   {
  42.     FT_Matrix  transform;
  43.  
  44.     FT_UNUSED( original );
  45.     /* we don't touch the advance width */
  46.     FT_UNUSED( advance );
  47.  
  48.  
  49.  
  50.     /* For italic, simply apply a shear transform, with an angle */
  51.     /* of about 12 degrees.                                      */
  52.  
  53.     transform.xx = 0x10000L;
  54.     transform.yx = 0x00000L;
  55.  
  56.     transform.xy = 0x06000L;
  57.     transform.yy = 0x10000L;
  58.  
  59.     FT_Outline_Transform( outline, &transform );
  60.  
  61.     return 0;
  62.   }
  63.  
  64.  
  65.   /*************************************************************************/
  66.   /*************************************************************************/
  67.   /****                                                                 ****/
  68.   /****   EXPERIMENTAL EMBOLDENING/OUTLINING SUPPORT                    ****/
  69.   /****                                                                 ****/
  70.   /*************************************************************************/
  71.   /*************************************************************************/
  72.  
  73.  
  74.   /* Compute the norm of a vector */
  75.  
  76. #ifdef FT_CONFIG_OPTION_OLD_CALCS
  77.  
  78.   static FT_Pos
  79.   ft_norm( FT_Vector*  vec )
  80.   {
  81.     FT_Int64  t1, t2;
  82.  
  83.  
  84.     MUL_64( vec->x, vec->x, t1 );
  85.     MUL_64( vec->y, vec->y, t2 );
  86.     ADD_64( t1, t2, t1 );
  87.  
  88.     return (FT_Pos)SQRT_64( t1 );
  89.   }
  90.  
  91. #else /* FT_CONFIG_OPTION_OLD_CALCS */
  92.  
  93.   static FT_Pos
  94.   ft_norm( FT_Vector*  vec )
  95.   {
  96.     FT_F26Dot6  u, v, d;
  97.     FT_Int      shift;
  98.     FT_ULong    H, L, L2, hi, lo, med;
  99.  
  100.  
  101.     u = vec->x; if ( u < 0 ) u = -u;
  102.     v = vec->y; if ( v < 0 ) v = -v;
  103.  
  104.     if ( u < v )
  105.     {
  106.       d = u;
  107.       u = v;
  108.       v = d;
  109.     }
  110.  
  111.     /* check that we are not trying to normalize zero! */
  112.     if ( u == 0 )
  113.       return 0;
  114.  
  115.     /* compute (u*u + v*v) on 64 bits with two 32-bit registers [H:L] */
  116.     hi  = (FT_ULong)u >> 16;
  117.     lo  = (FT_ULong)u & 0xFFFF;
  118.     med = hi * lo;
  119.  
  120.     H     = hi * hi + ( med >> 15 );
  121.     med <<= 17;
  122.     L     = lo * lo + med;
  123.     if ( L < med )
  124.       H++;
  125.  
  126.     hi  = (FT_ULong)v >> 16;
  127.     lo  = (FT_ULong)v & 0xFFFF;
  128.     med = hi * lo;
  129.  
  130.     H    += hi * hi + ( med >> 15 );
  131.     med <<= 17;
  132.     L2    = lo * lo + med;
  133.     if ( L2 < med )
  134.       H++;
  135.  
  136.     L += L2;
  137.     if ( L < L2 )
  138.       H++;
  139.  
  140.     /* if the value is smaller than 32 bits */
  141.     shift = 0;
  142.     if ( H == 0 )
  143.     {
  144.       while ( ( L & 0xC0000000UL ) == 0 )
  145.       {
  146.         L <<= 2;
  147.         shift++;
  148.       }
  149.       return ( FT_Sqrt32( L ) >> shift );
  150.     }
  151.     else
  152.     {
  153.       while ( H )
  154.       {
  155.         L   = ( L >> 2 ) | ( H << 30 );
  156.         H >>= 2;
  157.         shift++;
  158.       }
  159.       return ( FT_Sqrt32( L ) << shift );
  160.     }
  161.   }
  162.  
  163. #endif /* FT_CONFIG_OPTION_OLD_CALCS */
  164.  
  165.  
  166.   static int
  167.   ft_test_extrema( FT_Outline*  outline,
  168.                    int          n )
  169.   {
  170.     FT_Vector  *prev, *cur, *next;
  171.     FT_Pos      product;
  172.     FT_Int      c, first, last;
  173.  
  174.  
  175.     /* we need to compute the `previous' and `next' point */
  176.     /* for these extrema.                                 */
  177.     cur   = outline->points + n;
  178.     prev  = cur - 1;
  179.     next  = cur + 1;
  180.  
  181.     first = 0;
  182.     for ( c = 0; c < outline->n_contours; c++ )
  183.     {
  184.       last  = outline->contours[c];
  185.  
  186.       if ( n == first )
  187.         prev = outline->points + last;
  188.  
  189.       if ( n == last )
  190.         next = outline->points + first;
  191.  
  192.       first = last + 1;
  193.     }
  194.  
  195.     product = FT_MulDiv( cur->x - prev->x,   /* in.x  */
  196.                          next->y - cur->y,   /* out.y */
  197.                          0x40 )
  198.               -
  199.               FT_MulDiv( cur->y - prev->y,   /* in.y  */
  200.                          next->x - cur->x,   /* out.x */
  201.                          0x40 );
  202.  
  203.     if ( product )
  204.       product = product > 0 ? 1 : -1;
  205.  
  206.     return product;
  207.   }
  208.  
  209.  
  210.   /* Compute the orientation of path filling.  It differs between TrueType */
  211.   /* and Type1 formats.  We could use the `ft_outline_reverse_fill' flag,  */
  212.   /* but it is better to re-compute it directly (it seems that this flag   */
  213.   /* isn't correctly set for some weird composite glyphs currently).       */
  214.   /*                                                                       */
  215.   /* We do this by computing bounding box points, and computing their      */
  216.   /* curvature.                                                            */
  217.   /*                                                                       */
  218.   /* The function returns either 1 or -1.                                  */
  219.   /*                                                                       */
  220.   static int
  221.   ft_get_orientation( FT_Outline*  outline )
  222.   {
  223.     FT_BBox  box;
  224.     FT_BBox  indices;
  225.     int      n, last;
  226.  
  227.  
  228.     indices.xMin = -1;
  229.     indices.yMin = -1;
  230.     indices.xMax = -1;
  231.     indices.yMax = -1;
  232.  
  233.     box.xMin = box.yMin =  32767;
  234.     box.xMax = box.yMax = -32768;
  235.  
  236.     /* is it empty ? */
  237.     if ( outline->n_contours < 1 )
  238.       return 1;
  239.  
  240.     last = outline->contours[outline->n_contours - 1];
  241.  
  242.     for ( n = 0; n <= last; n++ )
  243.     {
  244.       FT_Pos  x, y;
  245.  
  246.  
  247.       x = outline->points[n].x;
  248.       if ( x < box.xMin )
  249.       {
  250.         box.xMin     = x;
  251.         indices.xMin = n;
  252.       }
  253.       if ( x > box.xMax )
  254.       {
  255.         box.xMax     = x;
  256.         indices.xMax = n;
  257.       }
  258.  
  259.       y = outline->points[n].y;
  260.       if ( y < box.yMin )
  261.       {
  262.         box.yMin     = y;
  263.         indices.yMin = n;
  264.       }
  265.       if ( y > box.yMax )
  266.       {
  267.         box.yMax     = y;
  268.         indices.yMax = n;
  269.       }
  270.     }
  271.  
  272.     /* test orientation of the xmin */
  273.     n = ft_test_extrema( outline, indices.xMin );
  274.     if ( n )
  275.       goto Exit;
  276.  
  277.     n = ft_test_extrema( outline, indices.yMin );
  278.     if ( n )
  279.       goto Exit;
  280.  
  281.     n = ft_test_extrema( outline, indices.xMax );
  282.     if ( n )
  283.       goto Exit;
  284.  
  285.     n = ft_test_extrema( outline, indices.yMax );
  286.     if ( !n )
  287.       n = 1;
  288.  
  289.   Exit:
  290.     return n;
  291.   }
  292.  
  293.  
  294.   FT_EXPORT_DEF( FT_Error )
  295.   FT_Outline_Embolden( FT_GlyphSlot original,
  296.                        FT_Outline*  outline,
  297.                        FT_Pos*      advance )
  298.   {
  299.     FT_Vector   u, v;
  300.     FT_Vector*  points;
  301.     FT_Vector   cur, prev, next;
  302.     FT_Pos      distance;
  303.     FT_Face     face = FT_SLOT_FACE( original );
  304.     int         c, n, first, orientation;
  305.  
  306.     FT_UNUSED( advance );
  307.  
  308.  
  309.     /* compute control distance */
  310.     distance = FT_MulFix( face->units_per_EM / 60,
  311.                           face->size->metrics.y_scale );
  312.  
  313.     orientation = ft_get_orientation( &original->outline );
  314.  
  315.     points = original->outline.points;
  316.  
  317.     first = 0;
  318.     for ( c = 0; c < outline->n_contours; c++ )
  319.     {
  320.       int  last = outline->contours[c];
  321.  
  322.  
  323.       prev = points[last];
  324.  
  325.       for ( n = first; n <= last; n++ )
  326.       {
  327.         FT_Pos     norm, delta, d;
  328.         FT_Vector  in, out;
  329.  
  330.  
  331.         cur = points[n];
  332.         if ( n < last ) next = points[n + 1];
  333.         else            next = points[first];
  334.  
  335.         /* compute the in and out vectors */
  336.         in.x  = cur.x - prev.x;
  337.         in.y  = cur.y - prev.y;
  338.  
  339.         out.x = next.x - cur.x;
  340.         out.y = next.y - cur.y;
  341.  
  342.         /* compute U and V */
  343.         norm = ft_norm( &in );
  344.         u.x = orientation *  FT_DivFix( in.y, norm );
  345.         u.y = orientation * -FT_DivFix( in.x, norm );
  346.  
  347.         norm = ft_norm( &out );
  348.         v.x = orientation *  FT_DivFix( out.y, norm );
  349.         v.y = orientation * -FT_DivFix( out.x, norm );
  350.  
  351.         d = distance;
  352.  
  353.         if ( ( outline->tags[n] & FT_Curve_Tag_On ) == 0 )
  354.           d *= 2;
  355.  
  356.         /* Check discriminant for parallel vectors */
  357.         delta = FT_MulFix( u.x, v.y ) - FT_MulFix( u.y, v.x );
  358.         if ( delta > FT_BOLD_THRESHOLD || delta < -FT_BOLD_THRESHOLD )
  359.         {
  360.           /* Move point -- compute A and B */
  361.           FT_Pos  x, y, A, B;
  362.  
  363.  
  364.           A = d + FT_MulFix( cur.x, u.x ) + FT_MulFix( cur.y, u.y );
  365.           B = d + FT_MulFix( cur.x, v.x ) + FT_MulFix( cur.y, v.y );
  366.  
  367.           x = FT_MulFix( A, v.y ) - FT_MulFix( B, u.y );
  368.           y = FT_MulFix( B, u.x ) - FT_MulFix( A, v.x );
  369.  
  370.           outline->points[n].x = distance + FT_DivFix( x, delta );
  371.           outline->points[n].y = distance + FT_DivFix( y, delta );
  372.         }
  373.         else
  374.         {
  375.           /* Vectors are nearly parallel */
  376.           FT_Pos  x, y;
  377.  
  378.  
  379.           x = distance + cur.x + FT_MulFix( d, u.x + v.x ) / 2;
  380.           y = distance + cur.y + FT_MulFix( d, u.y + v.y ) / 2;
  381.  
  382.           outline->points[n].x = x;
  383.           outline->points[n].y = y;
  384.         }
  385.  
  386.         prev = cur;
  387.       }
  388.  
  389.       first = last + 1;
  390.     }
  391.  
  392.     if ( advance )
  393.       *advance = ( *advance + distance * 4 ) & -64;
  394.  
  395.     return 0;
  396.   }
  397.  
  398.  
  399. /* END */
  400.